#pragma once
#include "cgzITask.h"

class cgzCTcpS;

enum ETCP_S
{
    TCPS_LOOP,
    TCPS_ACPT,
    TCPS_SEND,
    TCPS_RECV,
    TCPS_DISC,
    TCPS_GADD,
    TCPS_GDEL,
    TCPS_GCLR,
};

class cgzCLoopS : public cgzIData
{
public:
    friend class cgzCTcpS;
    cgzCLoopS(ETCP_S etype);
    virtual ~cgzCLoopS();

public:
    ETCP_S getEType() const;

private:
    ETCP_S type;
};

class cgzCAcptS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    cgzCAcptS(int fd, int ufd);
    virtual ~cgzCAcptS();

private:
    ETCP_S type;

public:
    int m_fd;
    int m_ufd;
};

class cgzCSendS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    // ufd设置
    cgzCSendS(const int ufd);
    // 客户端->网关->服务器
    cgzCSendS(cgzHeader &header, const int ufd);
    // 服务器->网关->客户端
    cgzCSendS(const int gfd, const int mid, const char *data, const int len, const int cfd, const long cid);
    // 普通消息
    cgzCSendS(const int ufd, const int mid, const int len, const long cid);
    cgzCSendS(const int ufd, const int mid, const char *data, const int len, const long cid);
    virtual ~cgzCSendS();

public:
    ETCP_S type;
    int m_ufd;
    int m_len;
    int m_sendlen;
    char *m_data;
};

class cgzCRecvS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    cgzCRecvS(const char *data, const int len, const int ufd, const int fd);
    cgzCRecvS(cgzHeader &header, const int ufd, const int fd);
    cgzCRecvS(cgzGateHeader &header, const int ufd, const int fd);
    virtual ~cgzCRecvS();

protected:
    ETCP_S type;

public:
    char *m_data;
    int m_len;
    int m_ufd;
    int m_fd;
};

class cgzCDiscS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    cgzCDiscS(int ufd, int fd);
    virtual ~cgzCDiscS();

private:
    ETCP_S type;

public:
    int m_ufd;
    int m_fd;
};

class cgzCGAddS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    cgzCGAddS();
    virtual ~cgzCGAddS();

public:
    std::unordered_map<int, int> map;
};

class cgzCGDelS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    cgzCGDelS();
    virtual ~cgzCGDelS();

public:
    std::unordered_set<int> set;
};

class cgzCGClrS : public cgzCLoopS
{
public:
    friend class cgzCTcpS;
    cgzCGClrS();
    virtual ~cgzCGClrS();
};

class cgzCTcpFd
{
    friend class cgzCTcpS;

public:
    cgzCTcpFd(int fd, int ufd);
    virtual ~cgzCTcpFd();

public:
    bool m_hand;
    int m_fd;
    int m_ufd;
    cgzCireBuffer m_recv;
};

class cgzCTcpS : public cgzITask
{
public:
    cgzCTcpS(
        cgzCThreadPool *pool,
        const char *name,
        const std::string ip,
        const int port,
        const int cid);
    virtual ~cgzCTcpS();

public:
    bool run(int64_t nms) override;
    bool casBusy() override;
    bool retTask(cgzIData *cgzTask) override;
    virtual bool run(cgzCLoopS *task);

public:
    virtual bool tcpbind();
    virtual bool tcpread();
    virtual bool tcpsend();
    virtual bool taccpet();

public:
    bool todoret(cgzIData *ctodo);
    bool disstcp(cgzCTcpFd *fdinfo);

public:
    virtual bool connect(int fd, bool is_hand = true);
    virtual bool handshake(cgzCTcpFd *fdinfo);
    virtual bool sendaccept(cgzCTcpFd *fdinfo);
    virtual bool sticking(cgzCTcpFd *fdinfo);

private:
    bool closeFd(int fd);

protected:
    std::string m_ip;
    int m_port;
    int m_cid;
    int m_sfd;
    int m_efd;
    int m_ufd;

protected:
    std::queue<cgzCSendS *> m_sendqueue; //{...}
    std::map<int, cgzCTcpFd *> m_fdmap;  //{[fd] = cgzCTcpFd}
    std::map<int, cgzCTcpFd *> m_ufdmap; //{[ufd] = cgzCTcpFd}
};

#define EPOOLEC 64